<?php

class Service_api extends MY_Service
{
    /**
     * @var array
     */
    private $info;

    /**
     * 本次请求的结果
     * @var array
     */
    private $result;

    public function __construct()
    {
        parent::__construct();
        $this->load->library('HttpUtil');
        $this->load->library('ArrayUtil');
        $this->load->library('PinyinUtil');
        $this->load->config('common/site_api');
    }

    /**
     * @param array $info
     * @return $this
     */
    public function setInfo($info)
    {
        $info = !empty($info) && is_string($info) ? json_decode($info, TRUE) : $info;
        $info['qConfig'] = !empty($info['qConfig']) && is_string($info['qConfig']) ? json_decode($info['qConfig'], TRUE) : $info['qConfig'];
        $info['params'] = !empty($info['params']) && is_string($info['params']) ? json_decode($info['params'], TRUE) : $info['params'];
        $info['rules'] = !empty($info['rules']) && is_string($info['rules']) ? json_decode($info['rules'], TRUE) : $info['rules'];
        $info['format'] = !empty($info['format']) && is_string($info['format']) ? json_decode($info['format'], TRUE) : $info['format'];
        // 处理分页
        $info['params'] = json_decode(str_replace("%{$info['qConfig']['next']['field']}%", $info['qConfig']['next']['value'], json_encode($info['params'])), TRUE);
        $this->info = $info;
        return $this;
    }

    /**
     * @return array
     */
    public function queryData()
    {
        $data = [];
        if(empty($this->info)){
            return $data;
        }

        return $this->_query();
    }

    /**
     * 处理下一页
     */
    public function dealNext()
    {
        if(!(bool)$this->info['qConfig']['is_all']){
            return FALSE;
        }

        $nextType = $this->info['qConfig']['next']['type'];
        switch($nextType){
            case 'int':
                $this->info['qConfig']['next']['value']++;
                break;
            case 'step':
                $this->info['qConfig']['next']['value'] += $this->info['qConfig']['next']['step'];
                break;
            case 'last':
                if((bool)ArrayUtil::dataGet($this->result, $this->info['qConfig']['next']['has_next_field'])){
                    $this->info['qConfig']['next']['value'] = ArrayUtil::dataGet($this->result, $this->info['qConfig']['next']['last_field']) ?: "";
                } else{
                    $this->info['qConfig']['next']['value'] = "";
                }
                break;
            default:
                break;
        }

        $this->load->model('Model_web_crawler_config');
        $this->Model_web_crawler_config->update(['qConfig' => json_encode($this->info['qConfig'], JSON_UNESCAPED_UNICODE), 'id' => $this->info['id']]);
    }

    /**
     * 存储解析结果
     * @param $data
     * @return false|void
     */
    public function addData($data)
    {
        if(!is_array($data)){
            return FALSE;
        }

        $this->load->model('Model_common');
        $this->Model_common->setTable($this->info['target']);
        $model = $this->Model_common;
        foreach($data as $item){
            if(empty($item[$this->info['qConfig']['check']['empty']])){
                echo "参数为空，跳过：" . json_encode($item, JSON_UNESCAPED_UNICODE) . PHP_EOL;
                continue;
            }

            $list = $model->getList(1, [$this->info['qConfig']['check']['cond'] => $item[$this->info['qConfig']['check']['cond']]]);
            if(empty($list)){
                $model->insert($item);
                echo "插入成功：" . json_encode($item, JSON_UNESCAPED_UNICODE) . PHP_EOL;
            } else{
                echo "已存在，跳过：" . json_encode($item, JSON_UNESCAPED_UNICODE) . PHP_EOL;
            }
        }
    }

    /**
     * 单次请求
     * @return array
     */
    private function _query()
    {
        $data = [];
        $site = $this->config->item('common');
        $site['url'] = $this->info['url'];

        switch($this->info['qConfig']['params']['type']){
            case 'json':
                $site['rawheaders']['Content-type'] = "application/json";
                $site['data'] = json_encode($this->info['params']);
                break;
            default:
                $site['data'] = $this->info['params'];
                break;
        }

        if(!empty($this->info['qConfig']['header'])){
            foreach($this->info['qConfig']['header'] as $key => $header){
                $site['rawheaders'][$key] = $header;
            }
        }

        $site['isPost'] = strtolower($this->info['qConfig']['type']) == 'post';
        $options['verify'] = FALSE;
        $res = HttpUtil::cfg_request_options($site, $options);
        if(empty($res)){
            return $data;
        }

        $this->result = json_decode($res, TRUE);
        return $this->_make();
    }

    /**
     * 组装结果
     * @return array
     */
    private function _make()
    {
        $data = [];
        // 取列表
        $list = ArrayUtil::dataGet($this->result, $this->info['range']);
        if(empty($list)){
            return $data;
        }

        // 取记录
        foreach($list as $item){
            $tmp = [];
            foreach($this->info['rules'] as $key => $rule){
                $tmp[$key] = ArrayUtil::dataGet($item, $rule);
            }
            $data[] = $tmp;
        }

        // 格式化记录
        foreach($data as &$item){
            $item = $this->format($item, $this->info['format']);
        }
        return $data;
    }

    /**
     * 格式化记录
     * @param $item
     * @param $formats
     * @return mixed
     */
    public function format($item, $formats)
    {
        foreach($formats as $key => $formatList){
            foreach($formatList as $format){
                switch($format['type']){
                    case 'pinyin':
                        $item[$key] = PinyinUtil::convert2Pinyin($item[$key]);
                        break;
                    case 'trim':
                        $item[$key] = trim($item[$key]);
                        break;
                    case 'replace':
                        $item[$key] = str_replace($format['search'], $format['replace'], $item[$key]);
                        break;
                    case '.':
                        $item[$key] = (!empty($format['pre']) ? $format['pre'] : "") . $item[$key] . (!empty($format['suffix']) ? $format['suffix'] : "");
                        break;
                    case 'preg_replace':
                        $item[$key] = preg_replace($format['search'], $format['replace'], $item[$key]);
                        break;
                    case 'array_column':
                        $item[$key] = array_column($item[$key], $format['key']);
                        break;
                    case 'implode':
                        $item[$key] = implode($format['split'], $item[$key]);
                        break;
                    case 'explode':
                        $item[$key] = explode($format['split'], $item[$key]);
                        break;
                    case 'real_url':
                        $realUrl = HttpUtil::real_url($item[$key]);
                        $item[$key] = !empty($realUrl) ? $realUrl : $item[$key];
                        break;
                    case 'img2base64':
                        $this->load->service('Service_icon');
                        $item[$key] = $this->Service_icon->url2base64($item[$key]);
                        break;
                    default:
                        break;
                }
            }
        }
        return $item;
    }
}